﻿/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using Microsoft.DirectX.Direct3D;

namespace Daidalos.UI
{
    public abstract class Control
    {
        public enum ControlState
        {
            Normal,
            Over,
            Down,
            Disabled
        };

        public enum TextAlign
        {
            Left,
            Right,
            Top,
            Bottom,
            Center
        };

        #region Attributes
        /// <summary>
        /// 
        /// </summary>
        private int id;

        /// <summary>
        /// 
        /// </summary>
        private List<Sprite> quads;

        /// <summary>
        /// 
        /// </summary>
        private List<Sprite> fontQuads;

        /// <summary>
        /// 
        /// </summary>
        private Rectangle hotspot;

        /// <summary>
        /// 
        /// </summary>
        private ControlState state;

        /// <summary>
        /// 
        /// </summary>
        private bool disabled;

        /// <summary>
        /// 
        /// </summary>
        private TextAlign textalign;

        /// <summary>
        /// 
        /// </summary>
        private RectangleF textRec;

        /// <summary>
        /// 
        /// </summary>
        private SizeF size;

        /// <summary>
        /// 
        /// </summary>
        private bool hasFocus;

        /// <summary>
        /// 
        /// </summary>
        private bool mouseDown;

        /// <summary>
        /// 
        /// </summary>
        private object data;

        /// <summary>
        /// 
        /// </summary>
        private int zdepth;

        /// <summary>
        /// 
        /// </summary>
        private string text = string.Empty;

        /// <summary>
        /// 
        /// </summary>
        protected bool hasTouchDownPoint;

        /// <summary>
        /// 
        /// </summary>
        protected Point touchDownPoint;
        
        /// <summary>
        /// 
        /// </summary>
        protected PointF position;
        
        /// <summary>
        /// 
        /// </summary>
        protected Font.BitmapString font;

        /// <summary>
        /// 
        /// </summary>
        protected float fontSize;

        /// <summary>
        /// 
        /// </summary>
        protected ColorValue textColor;

        /// <summary>
        /// 
        /// </summary>
        protected float fontPadding;

        /// <summary>
        /// 
        /// </summary>
        protected int fontStartVertex;

        /// <summary>
        /// 
        /// </summary>
        protected int startVertex;

        /// <summary>
        /// 
        /// </summary>
        private int panelID;
        #endregion


        #region Accessors
        /// <summary>
        /// 
        /// </summary>
        public int Id
        {
            get 
            { 
                return id; 
            }
            set 
            { 
                id = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public List<Sprite> Quads
        {
            get 
            {
                return quads; 
            }
            set 
            { 
                quads = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public List<Sprite> FontQuads
        {
            get 
            {
                return fontQuads; 
            }
            set 
            {
                fontQuads = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public Rectangle Hotspot
        {
            get 
            {
                return hotspot; 
            }
            set 
            {
                hotspot = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public ControlState State
        {
            get 
            {
                return state; 
            }
            set 
            {
                state = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public TextAlign Textalign
        {
            get 
            {
                return textalign; 
            }
            set 
            {
                textalign = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public RectangleF TextRec
        {
            get 
            {
                return textRec; 
            }
            set 
            {
                textRec = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public SizeF Size
        {
            get 
            {
                return size; 
            }
            set 
            {
                size = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public bool Disabled
        {
            get 
            {
                return disabled; 
            }
            set 
            {
                disabled = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public bool HasFocus
        {
            get 
            {
                return hasFocus; 
            }
            set 
            {
                hasFocus = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public bool MouseDown
        {
            get 
            {
                return mouseDown; 
            }
            set 
            {
                mouseDown = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public object Data
        {
            get 
            {
                return data; 
            }
            set 
            {
                data = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public int ZDepth
        {
            get 
            {
                return zdepth; 
            }
            set 
            {
                zdepth = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public string Text
        {
            get 
            {
                return text; 
            }
            set 
            {
                text = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public bool HasTouchDownPoint
        {
            get 
            {
                return hasTouchDownPoint; 
            }
            set 
            {
                hasTouchDownPoint = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public Point TouchDownPoint
        {
            get 
            {
                return touchDownPoint; 
            }
            set 
            {
                touchDownPoint = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public PointF Position
        {
            get 
            {
                return position; 
            }
            set 
            {
                position = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public Font.BitmapString Font
        {
            get 
            {
                return font; 
            }
            set 
            {
                font = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public float FontSize
        {
            get 
            {
                return fontSize; 
            }
            set {
                fontSize = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public ColorValue TextColor
        {
            get 
            { 
                return textColor; 
            }
            set 
            { 
                textColor = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public float FontPadding
        {
            get 
            { 
                return fontPadding; 
            }
            set 
            { 
                fontPadding = value; 
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public int StartVertex
        {
            get 
            { 
                return startVertex; 
            }
            set 
            { 
                startVertex = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public int FontStartVertex
        {
            get 
            { 
                return fontStartVertex; 
            }
            set 
            { 
                fontStartVertex = value; 
            }
        }
        
        /// <summary>
        /// 
        /// </summary>
        public int PanelID
        {
            get 
            { 
                return panelID; 
            }
            set 
            { 
                panelID = value; 
            }
        }
        #endregion

        public event GuiManager.ControlDelegate OnControl;

        #region Methods
        /// <summary>
        /// 
        /// </summary>
        public Control()
        {
            PanelID = 0;
            FontPadding = 5f;
            State = ControlState.Normal;
            TextRec = new RectangleF();
            Quads = new List<Sprite>();
            FontQuads = new List<Sprite>();
            Disabled = false;
            HasFocus = false;
            HasTouchDownPoint = false;
            MouseDown = false;
            Data = null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cursor"></param>
        /// <param name="buttons"></param>
        /// <param name="zDelta"></param>
        /// <returns></returns>
        public bool MouseHandler(Point cursor, bool[] buttons, float zDelta)
        {
            if (!HasTouchDownPoint && buttons[0])
            {
                TouchDownPoint = cursor;
                HasTouchDownPoint = true;
            }
            else if (HasTouchDownPoint && !buttons[0])
            {
                HasTouchDownPoint = false;
            }

            if((!(this is EditBox) && (Contains(cursor) || HasFocus)) || ((this is EditBox)
                && Contains(cursor)))
            {
                if (zDelta != 0.0f)
                {
                    OnZDelta(zDelta);
                }

                if (!buttons[0])
                {
                    if (MouseDown)
                    {
                        MouseDown = false;
                        if (this is EditBox)
                        {
                            HasFocus = !HasFocus;
                        }
                        else
                            HasFocus = false;

                        if (Contains(cursor))
                        {
                            OnMouseRelease(cursor);
                            if (OnControl != null && !(this is Panel) && (!(this is ListBox) ||
                                ((this is ListBox) && (this as ListBox).HasNewData)))
                            {
                                OnControl(Id, Data);
                            }
                        }
                    }
                    bool result = true;

                    if (State == ControlState.Over && !(this is ListBox) && !(this is Panel))
                    {
                        result = false;
                    }

                    State = ControlState.Over;
                    OnMouseOver(cursor, buttons);
                    return result;
                }
                else if (buttons[0] && HasTouchDownPoint && Contains(TouchDownPoint) || HasFocus)
                {
                    State = ControlState.Down;
                    OnMouseDown(cursor, buttons);

                    if ((this is Slider) && OnControl != null)
                    {
                        OnControl(Id, Data);
                    }

                    MouseDown = true;

                    if (!(this is EditBox))
                    {
                        HasFocus = true;
                    }
                    return true;
                }
            }
            else if (!Contains(cursor) && State != ControlState.Normal)
            {
                if (!buttons[0] && !(this is EditBox))
                {
                    HasFocus = false;
                }
                if (!HasFocus)
                {
                    State = ControlState.Normal;
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pressedKeys"></param>
        /// <param name="pressedChar"></param>
        /// <param name="pressedKey"></param>
        /// <returns></returns>
        public virtual bool KeyboardHandler(List<System.Windows.Forms.Keys> pressedKeys,
            char pressedChar, int pressedKey)
        {
            if (OnKeyDown(pressedKeys, pressedChar, pressedKey))
            {
                if (OnControl != null)
                {
                    OnControl(Id, Data);
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pressedKeys"></param>
        /// <param name="pressedChar"></param>
        /// <param name="pressedKey"></param>
        /// <returns></returns>
        public virtual bool OnKeyDown(List<System.Windows.Forms.Keys> pressedKeys,
            char pressedChar, int pressedKey)
        {
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cursor"></param>
        /// <param name="buttons"></param>
        protected virtual void OnMouseOver(Point cursor, bool[] buttons)
        { 
            // Empty
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cursor"></param>
        /// <param name="buttons"></param>
        protected virtual void OnMouseDown(Point cursor, bool[] buttons)
        { 
            // Empty
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cursor"></param>
        protected virtual void OnMouseRelease(Point cursor)
        {
            // Empty
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="zDelta"></param>
        protected virtual void OnZDelta(float zDelta)
        {
            // Empty
        }

        /// <summary>
        /// 
        /// </summary>
        protected virtual void BuildText()
        {
            // Empty
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="cursor"></param>
        /// <returns></returns>
        public bool Contains(Point cursor)
        {
            return Hotspot.Contains(cursor);
        }
        #endregion
    }
}
